/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate alloc;

use crate::common::constants::*;
use crate::common::types::*;
use crate::entry::user_auth_ffi::CommandId;
use crate::entry::user_auth_ffi::*;
use crate::traits::command_manager::{AccessPolicy, CommandHandler};
use crate::traits::config_manager::{ConfigManagerRegistry};
use crate::traits::misc_manager::{MiscManagerRegistry};
use crate::traits::edit_session_manager::EditSessionManagerRegistry;
use crate::traits::executor_manager::{ExecutorInfo, ExecutorManagerRegistry};
use crate::traits::time_keeper::TimeKeeperRegistry;
use crate::traits::user_db_manager::{UserDbManagerRegistry, Credential};
use crate::utils::auth_token::AuthToken;
use crate::{impl_command_handler, log_e, log_i, Box};
use crate::jobs::clear_user_db_redundancy_info::clear_user_db_redundancy_info;
use crate::Vec;
use core::convert::TryFrom;
//todo
static mut INIT_FLAG: bool = false;

// Init - implementation
pub type InitInput = InitInputFfi;
pub type InitOutput = InitOutputFfi;

pub trait InitCommandExecutor {
    fn execute(&self, input: InitInputFfi) -> Result<InitOutput, ErrorCode>;
}

pub struct DefaultInitCommandExecutor;

impl InitCommandExecutor for DefaultInitCommandExecutor {
    fn execute(&self, _input: InitInput) -> Result<InitOutput, ErrorCode> {
        let output: InitOutput = InitOutput::default();
        if unsafe {INIT_FLAG} {
            log_i!("userAuth already init");
            return Ok(output);
        }
        //todo 不需要initContext， initResourcePoll, esecret没有init
        MiscManagerRegistry::get_mut().set_udid(Udid(_input.device_udid))?;
        MiscManagerRegistry::get_mut().get_local_key_pair()?;
        UserDbManagerRegistry::get_mut().read_db()?;
        clear_user_db_redundancy_info()?;
        ConfigManagerRegistry::get_mut().load_from_storage()?;
        unsafe {INIT_FLAG = true;}
        Ok(output)
    }
}

crate::impl_command_handler!(
    InitCommandHandler,
    InitInputFfi,
    InitInput,
    InitOutputFfi,
    Box<dyn InitCommandExecutor>
);

// SetGlobalConfigParam - implementation
#[derive(Clone)]
pub struct GlobalConfigParam {
    pub type_: ConfigType,
    pub pin_expired_period: i64,
    pub enable_status: bool,
    pub user_ids: Vec<i32>,
    pub auth_types: Vec<AuthType>,
}

impl TryFrom<GlobalConfigParamFfi> for GlobalConfigParam {
    type Error = ErrorCode;

    fn try_from(ffi: GlobalConfigParamFfi) -> Result<Self, ErrorCode> {
        Ok(GlobalConfigParam {
            type_: ConfigType::try_from(ffi.type_)?,
            pin_expired_period: ffi.pin_expired_period,
            enable_status: ffi.enable_status != 0,
            user_ids: Vec::try_from(ffi.user_ids)?,
            auth_types: Vec::try_from(ffi.auth_types)?,
        })
    }
}

#[derive(Clone, Default)]
pub struct ExecutorExpiredInfo {
    pub schedule_id: u64,
    pub schedule_mode: u32,
    pub auth_expired_sys_time: u64,
}

impl TryFrom<ExecutorExpiredInfo> for ExecutorExpiredInfoFfi {
    type Error = ErrorCode;

    fn try_from(info: ExecutorExpiredInfo) -> Result<Self, ErrorCode> {
        Ok(ExecutorExpiredInfoFfi {
            schedule_id: info.schedule_id,
            schedule_mode: info.schedule_mode,
            auth_expired_sys_time: info.auth_expired_sys_time,
        })
    }
}

#[derive(Clone)]
pub struct SetGlobalConfigParamInput {
    pub param: GlobalConfigParam,
}

impl TryFrom<SetGlobalConfigParamInputFfi> for SetGlobalConfigParamInput {
    type Error = ErrorCode;

    fn try_from(ffi: SetGlobalConfigParamInputFfi) -> Result<Self, ErrorCode> {
        Ok(SetGlobalConfigParamInput {
            param: ffi.param.try_into()?,
        })
    }
}

#[derive(Clone, Default)]
pub struct SetGlobalConfigParamOutput {
    pub param: ExecutorExpiredInfo,
}

impl TryFrom<SetGlobalConfigParamOutput> for SetGlobalConfigParamOutputFfi {
    type Error = ErrorCode;

    fn try_from(ffi: SetGlobalConfigParamOutput) -> Result<Self, ErrorCode> {
        Ok(SetGlobalConfigParamOutputFfi {
            param: ffi.param.try_into()?,
        })
    }
}

pub trait SetGlobalConfigParamCommandExecutor {
    fn execute(
        &self,
        input: SetGlobalConfigParamInput,
    ) -> Result<SetGlobalConfigParamOutput, ErrorCode>;
}

pub struct DefaultSetGlobalConfigParamCommandExecutor;

impl SetGlobalConfigParamCommandExecutor for DefaultSetGlobalConfigParamCommandExecutor {
    fn execute(
        &self,
        _input: SetGlobalConfigParamInput,
    ) -> Result<SetGlobalConfigParamOutput, ErrorCode> {
        let output: SetGlobalConfigParamOutput = SetGlobalConfigParamOutput::default();
        match _input.param.type_ {
            ConfigType::PinExpiredPeriod => {
                ConfigManagerRegistry::get_mut().set_pin_expired_period(_input.param.pin_expired_period)?;
                //todo setContextExpiredTime
                return Ok(output);
            },
            ConfigType::AuthTypeEnableStatus => {
                for auth_type in _input.param.auth_types {
                    ConfigManagerRegistry::get_mut().set_enable_status(auth_type, _input.param.enable_status,
                        &_input.param.user_ids)?;
                }
                return Ok(output);
            },
            _ => Err(ErrorCode::BadParam)

        }
    }
}

crate::impl_command_handler!(
    SetGlobalConfigParamCommandHandler,
    SetGlobalConfigParamInputFfi,
    SetGlobalConfigParamInput,
    SetGlobalConfigParamOutputFfi,
    Box<dyn SetGlobalConfigParamCommandExecutor>
);

// AddExecutor - implementation
#[derive(Clone)]
pub struct ExecutorRegisterInfo {
    pub auth_type: AuthType,
    pub executor_role: ExecutorRole,
    pub executor_sensor_hint: u32,
    pub executor_matcher: u32,
    pub esl: ExecutorSecurityLevel,
    pub max_template_acl: u32,
    pub public_key: [u8; PUBLIC_KEY_LEN],
    pub device_udid: Udid,
    pub signed_remote_executor_info: Vec<u8>,
}

impl TryFrom<ExecutorRegisterInfoFfi> for ExecutorRegisterInfo {
    type Error = ErrorCode;

    fn try_from(ffi: ExecutorRegisterInfoFfi) -> Result<Self, ErrorCode> {
        Ok(ExecutorRegisterInfo {
            auth_type: AuthType::try_from(ffi.auth_type)?,
            executor_role: ExecutorRole::try_from(ffi.executor_role)?,
            executor_sensor_hint: ffi.executor_sensor_hint,
            executor_matcher: ffi.executor_matcher,
            esl: ExecutorSecurityLevel::try_from(ffi.esl)?,
            max_template_acl: ffi.max_template_acl as u32,
            public_key: ffi.public_key,
            device_udid: Udid(ffi.device_udid),
            signed_remote_executor_info: Vec::try_from(ffi.signed_remote_executor_info)?,
        })
    }
}

#[derive(Clone)]
pub struct AddExecutorInput {
    pub info: ExecutorRegisterInfo,
}

impl TryFrom<AddExecutorInputFfi> for AddExecutorInput {
    type Error = ErrorCode;

    fn try_from(ffi: AddExecutorInputFfi) -> Result<Self, ErrorCode> {
        Ok(AddExecutorInput {
            info: ffi.info.try_into()?,
        })
    }
}

#[derive(Clone)]
pub struct AddExecutorOutput {
    pub index: u64,
    pub public_key: [u8; PUBLIC_KEY_LEN],
    pub template_ids: Vec<TemplateId>,
}

impl TryFrom<AddExecutorOutput> for AddExecutorOutputFfi {
    type Error = ErrorCode;

    fn try_from(output: AddExecutorOutput) -> Result<Self, ErrorCode> {
        Ok(AddExecutorOutputFfi {
            index: output.index,
            public_key: output.public_key,
            template_ids: output.template_ids.try_into()?,
        })
    }
}

pub trait AddExecutorCommandExecutor {
    fn execute(&self, input: AddExecutorInput) -> Result<AddExecutorOutput, ErrorCode>;
}

pub struct DefaultAddExecutorCommandExecutor;

impl AddExecutorCommandExecutor for DefaultAddExecutorCommandExecutor {
    fn execute(&self, input: AddExecutorInput) -> Result<AddExecutorOutput, ErrorCode> {
        let public_key = self.get_framework_public_key()?;

        let executor_register_info = input.info;

        let executor_info = self.generate_executor_info(&executor_register_info, public_key)?;

        let executor_index = ExecutorManagerRegistry::get_mut().register(&executor_info)?;

        let template_ids = self.get_template_id_list(executor_register_info.auth_type)?;

        let add_executor_output = AddExecutorOutput{
            index: executor_index,
            public_key: public_key,
            template_ids: template_ids
        };

        Ok(add_executor_output)
    }
}

impl DefaultAddExecutorCommandExecutor {
    fn get_framework_public_key(&self) -> Result<[u8; PUBLIC_KEY_LEN], ErrorCode> {
        //公钥从哪里拿？？？？
        let public_key = [0u8; PUBLIC_KEY_LEN];
        Ok(public_key)
    }

    fn generate_executor_info(&self, executor_register_info: &ExecutorRegisterInfo, public_key: [u8; PUBLIC_KEY_LEN]) -> Result<ExecutorInfo, ErrorCode> {
        let executor_index = 0;
        let auth_type = executor_register_info.auth_type;
        let matcher = executor_register_info.executor_matcher;
        let esl = executor_register_info.esl;
        let max_template_acl = AuthCapabilityLevel::try_from(executor_register_info.max_template_acl)?;
        let role = executor_register_info.executor_role;
        let sensor_hint = executor_register_info.executor_sensor_hint;
        let device_udid = executor_register_info.device_udid;

        let executor_info = ExecutorInfo {
            executor_index: executor_index,
            auth_type: auth_type,
            matcher: matcher,
            esl: esl,
            max_template_acl: max_template_acl,
            role: role,
            sensor_hint: sensor_hint,
            public_key: public_key,
            device_udid: device_udid
        };
        
        Ok(executor_info)
    }

    fn get_template_id_list(&self, auth_type: AuthType) -> Result<Vec<TemplateId>, ErrorCode> {
        let filter = Box::new(move |cred: &Credential| {
            cred.auth_type == auth_type
        });
        
        let credential_list = UserDbManagerRegistry::get().get_credential_list(filter)?;
        
        // 遍历 credential_list，提取 template_id 并收集到 Vec
        let template_ids = credential_list
            .iter()
            .map(|cred| cred.template_id.clone())
            .collect::<Vec<TemplateId>>();
        
        Ok(template_ids)
    }
}


impl_command_handler!(
    AddExecutorCommandHandler,
    AddExecutorInputFfi,
    AddExecutorInput,
    AddExecutorOutputFfi,
    Box<dyn AddExecutorCommandExecutor>
);

// DeleteExecutor - implementation
pub type DeleteExecutorInput = DeleteExecutorInputFfi;
pub type DeleteExecutorOutput = DeleteExecutorOutputFfi;

pub trait DeleteExecutorCommandExecutor {
    fn execute(&self, input: DeleteExecutorInput) -> Result<DeleteExecutorOutput, ErrorCode>;
}

pub struct DefaultDeleteExecutorCommandExecutor;

impl DeleteExecutorCommandExecutor for DefaultDeleteExecutorCommandExecutor {
    fn execute(&self, input: DeleteExecutorInput) -> Result<DeleteExecutorOutput, ErrorCode> {
        let executor_index = input.index;
        ExecutorManagerRegistry::get_mut().unregister(executor_index);
        Ok(PlaceHolderFfi {
            place_holder: 0
        })
    }
}

impl_command_handler!(
    DeleteExecutorCommandHandler,
    DeleteExecutorInputFfi,
    DeleteExecutorInput,
    DeleteExecutorOutputFfi,
    Box<dyn DeleteExecutorCommandExecutor>
);

// VerifyAuthToken - implementation
pub type VerifyAuthTokenInput = VerifyAuthTokenInputFfi;
pub type VerifyAuthTokenOutput = VerifyAuthTokenOutputFfi;

pub trait VerifyAuthTokenCommandExecutor {
    fn execute(&self, input: VerifyAuthTokenInput) -> Result<VerifyAuthTokenOutput, ErrorCode>;
}

pub struct DefaultVerifyAuthTokenCommandExecutor;

impl VerifyAuthTokenCommandExecutor for DefaultVerifyAuthTokenCommandExecutor {
    fn execute(&self, input: VerifyAuthTokenInput) -> Result<VerifyAuthTokenOutput, ErrorCode> {
        let allowable_duration = input.allowable_duration;
        let user_auth_token_hal_slice = Vec::try_from(input.token_in)?;

        let auth_token = AuthToken::decode_from_slice(&user_auth_token_hal_slice, allowable_duration)?;

        let version = 0;
        let user_id = auth_token.user_id;
        let challenge = auth_token.challenge;
        let auth_trust_level = auth_token.auth_trust_level as i32;
        let auth_type = auth_token.auth_type as i32;
        let auth_mode = auth_token.schedule_mode as i32;
        let security_level = auth_token.security_level  as u32;
        let token_type = auth_token.token_type as i32;
        let secure_uid = auth_token.secure_uid;
        let enrolled_id = auth_token.enrolled_id;
        let credential_id = auth_token.credential_id.0;
        let collector_udid = auth_token.collector_udid.0;
        let verifier_udid = auth_token.verifier_udid.0;

        let time_interval = self.get_time_interval(auth_token.time)?;

        let root_secret = self.get_root_secret(auth_token)?;

        let output = VerifyAuthTokenOutput {
            version: version,
            user_id: user_id,
            challenge: challenge,
            time_interval: time_interval,
            auth_trust_level: auth_trust_level,
            auth_type: auth_type,
            auth_mode: auth_mode,
            security_level: security_level,
            token_type: token_type,
            secure_uid: secure_uid,
            enrolled_id: enrolled_id,
            credential_id: credential_id,
            collector_udid: collector_udid,
            verifier_udid: verifier_udid,
            root_secret: root_secret
        };

        Ok(output)
    }
}

impl DefaultVerifyAuthTokenCommandExecutor {
    fn get_time_interval(&self, token_sign_time: u64) -> Result<u64, ErrorCode> {
        let current_time = TimeKeeperRegistry::get().get_system_time()?;
        if current_time < token_sign_time {
            return Err(ErrorCode::GeneralError);
        }
        
        let time_interval = current_time - token_sign_time;
        Ok(time_interval)
    }

    fn get_root_secret(&self, auth_token: AuthToken) -> Result<RootSecret, ErrorCode> {
        EditSessionManagerRegistry::get_mut().get_edit_session()?.check_valid(Some(auth_token.user_id))?;

        let is_time_valid = EditSessionManagerRegistry::get_mut().get_edit_session()?.is_token_time_valid(auth_token.time);

        if !is_time_valid {
            log_e!("check token time failed, token is invalid");
            return Err(ErrorCode::GeneralError);
        }

        let session_challenge = EditSessionManagerRegistry::get_mut().get_edit_session()?.challenge();

        if auth_token.challenge != *session_challenge {
            log_e!("check challenge failed, token is invalid");
            return Err(ErrorCode::GeneralError);
        }

        let auth_type = auth_token.auth_type;
        if auth_type != AuthType::Pin {
            log_e!("token auth type is not pin");
            return Ok([0u8; ROOT_SECRET_LEN_FFI])
        }

        let root_secret = EditSessionManagerRegistry::get_mut().get_edit_session()?.get_root_secret()?.clone();

        Ok(root_secret)
    }
}

impl_command_handler!(
    VerifyAuthTokenCommandHandler,
    VerifyAuthTokenInputFfi,
    VerifyAuthTokenInput,
    VerifyAuthTokenOutputFfi,
    Box<dyn VerifyAuthTokenCommandExecutor>
);
